#include <iostream>
#include "util.hpp"
#include "message.hpp"
#include "Format.hpp"
#include "sink.hpp"
#include "logger.hpp"
#include <unistd.h>
#include "buffer.hpp"
#include "log.hpp"

using namespace std;
using namespace log_util;

enum class TimeGap
{
    Gap_second,
    Gap_minute,
    Gap_hour,
    Gap_day
};
class RollByTimeSink : public LogSink
{
private:
    string _basename;
    ofstream _ofs;
    size_t _gap;
    size_t _cur_gap;
    string createNewFile()
    {
        time_t t = log_util::date::now();
        struct tm lt;
        localtime_r(&t, &lt);
        stringstream filename;
        filename << _basename;
        filename << lt.tm_year;
        filename << lt.tm_mon;
        filename << lt.tm_mday;
        filename << lt.tm_hour;
        filename << lt.tm_min;
        filename << lt.tm_sec;
        filename << ".log";
        return filename.str();
    }

public:
    using ptr = shared_ptr<FileSink>;
    RollByTimeSink(const string &basename, TimeGap gap_type) : _basename(basename)
    {
        switch (gap_type)
        {
        case TimeGap::Gap_second:
            _gap = 1;
            break;
        case TimeGap::Gap_minute:
            _gap = 60;
            break;
        case TimeGap::Gap_hour:
            _gap = 3600;
            break;
        case TimeGap::Gap_day:
            _gap = 3600 * 24;
            break;
        }
        // _cur_gap = _gap==1?log_util::date::now():log_util::date::now()%_gap;
        _cur_gap = log_util::date::now() / _gap;
        string filename = createNewFile();
        log_util::file::create_directory(log_util::file::path(filename));
        _ofs.open(filename, ios::binary | ios::app);
        assert(_ofs.is_open());
    }
    void log(const char *data, size_t len)
    {
        time_t cur = log_util::date::now();
        if ((cur / _gap) != _cur_gap)
        {
            _ofs.close();
            string pathname = createNewFile();
            _ofs.open(pathname, std::ios::binary | ios::app);
            assert(_ofs.is_open());
        }
        _ofs.write(data, len);
        assert(_ofs.good());
    }
};

void testlog()
{
    // Logger::ptr logger = getLogger("Async_logger");
    // logger->debug("%s","测试日志");
    // logger->info("%s","测试日志");
    // logger->warn("%s","测试日志");
    // logger->error("%s","测试日志");
    // logger->fatal("%s","测试日志");

    DEBUG("%s","测试日志");
    INFO("%s","测试日志");
    WARN("%s","测试日志");
    ERROR("%s","测试日志");
    FATAL("%s","测试日志");

    size_t count=0;
    while(count<5000)
    {
        FATAL("测试日志-%d",count++);
    }
}

int main()
{
    // Logger::ptr logger = LoggerManager::getInstance().rootLogger();

    // logger->debug(__FILE__, __LINE__, "%s", "测试日志");
    // logger->info(__FILE__, __LINE__, "%s", "测试日志");
    // logger->warn(__FILE__, __LINE__, "%s", "测试日志");
    // logger->error(__FILE__, __LINE__, "%s", "测试日志");
    // logger->fatal(__FILE__, __LINE__, "%s", "测试日志");

    // size_t cursize = 0, count = 0;
    // while (count < 5000)
    // {
    //     logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++);
    // }



    unique_ptr<LoggerBuilder> builder(new GlobalLoggerBuilder());
    builder->buildLoggerName("Async_logger");
    builder->buildLoggerLevel(LogLevel::value::Warn);
    //builder->buildFormatter("%m%n");
    //builder->buildLoggerType(LoggerType::LOGGER_ASYNC);
    builder->buildSink<FileSink>("./logfile/test.log");
    builder->buildSink<StdoutSink>();
    builder->build();
    testlog();

    // test_log();

    // ifstream ifs("./logfile/test.log", std::ios::binary);
    // if (ifs.is_open() == false)
    //     return -1;

    // ifs.seekg(0, std::ios::end); // 读写位置跳转到文件末尾
    // size_t fsize = ifs.tellg();  // 获取当前读写位置相对于起始位置的偏移量
    // ifs.seekg(0, std::ios::beg); // 重新跳转起始位置
    // string body;
    // body.resize(fsize);
    // ifs.read(&body[0], fsize);
    // if (ifs.good() == false)
    // {
    //     cout << "read error" << endl;
    //     return -1;
    // }
    // ifs.close();
    // cout<<body.size()<<endl;
    // Buffer buffer;
    // for(int i=0;i<body.size();++i)
    // {
    //     buffer.push(&body[i],1);
    // }
    // cout<<buffer.readAbleSize()<<endl;
    // ofstream ofs("./logfile/tem.log",ios::binary);
    // size_t rsize = buffer.readAbleSize();
    // for(int i=0;i<rsize;++i)
    // {
    //     ofs.write(buffer.begin(),1);
    //     buffer.moveReader(1);
    // }

    // ofs.close();

    // string logger_name = "sync_logger";
    // LogLevel::value limit = LogLevel::value::Warn;
    // Formatter::ptr fmt(new Formatter("[%d{%H:%M:%S}][%t][%p][%c][%f:%l] %m%n"));
    // LogSink::ptr stdout_lsp = SinkFactory::create<StdoutSink>();
    // LogSink::ptr file_lsp = SinkFactory::create<FileSink>("./logfile/test.log");
    // LogSink::ptr roll_lsp = SinkFactory::create<RollBySizeSink>("./logfile/roll-", 1024 * 1024);
    // vector<LogSink::ptr> sinks = {stdout_lsp,file_lsp,roll_lsp};
    // Logger::ptr logger(new SynLogger(logger_name,limit,fmt,sinks));

    // unique_ptr<LoggerBuilder> builder(new LocalLoggerBuilder());
    // builder->buildLoggerName("sync_logger");
    // builder->buildLoggerLevel(LogLevel::value::Warn);
    // builder->buildFormatter("%m%n");
    // builder->buildLoggerType(LoggerType::LOGGER_SYNC);
    // builder->buildSink<FileSink>("./logfile/test.log");
    // //builder->buildSink<StdoutSink>();
    // Logger::ptr logger = builder->build();

    // logger->debug(__FILE__,__LINE__,"%s","测试日志");
    // logger->info(__FILE__,__LINE__,"%s","测试日志");
    // logger->warn(__FILE__,__LINE__,"%s","测试日志");
    // logger->error(__FILE__,__LINE__,"%s","测试日志");
    // logger->fatal(__FILE__,__LINE__,"%s","测试日志");

    // size_t cursize =0,count=0;
    // while(cursize<1024*1024*10)
    // {
    //     logger->fatal(__FILE__,__LINE__,"测试日志-%d",count++);
    //     cursize+=20;
    // }

    // LogMsg msg("root", "main.cc", 53, "格式化功能测试....", LogLevel::value::Info);

    // Formatter fmt;
    // string str = fmt.format(msg);

    // // LogSink::ptr stdout_lsp = SinkFactory::create<StdoutSink>();
    // // LogSink::ptr file_lsp = SinkFactory::create<FileSink>("./logfile/test.log");
    // // LogSink::ptr roll_lsp = SinkFactory::create<RollBySizeSink>("./logfile/roll-", 1024 * 1024);
    // LogSink::ptr time_lsp = SinkFactory::create<RollByTimeSink>("./logfile/roll-",TimeGap::Gap_second);
    // time_t old = log_util::date::now();
    // while(log_util::date::now()<old+5)
    // {
    //     time_lsp->log(str.c_str(),str.size());
    //     usleep(1000);
    // }

    // stdout_lsp->log(str.c_str(), str.size());
    // file_lsp->log(str.c_str(), str.size());
    // size_t cursize = 0;
    // size_t count = 0;
    // while (cursize < 1024 * 1024 * 10)
    // {
    //     string tem = str + std::to_string(count++);
    //     roll_lsp->log(tem.c_str(), tem.size());
    //     cursize += tem.size();
    // }

    // cout << log_util::date::now() << endl;

    // string _path = file::path("./abc/dcb/efg/");

    // if (!file::exists(_path))
    // {
    //     file::create_directory(_path);
    // }
    return 0;
}
